

<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>Definition文件 &mdash; Singularity container 3.5 documentation</title>
  

  
  
    <link rel="shortcut icon" href="_static/favicon.png"/>
  
  
  

  
  <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
  
    
      <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
        <script src="_static/jquery.js"></script>
        <script src="_static/underscore.js"></script>
        <script src="_static/doctools.js"></script>
        <script src="_static/language_data.js"></script>
        <script src="_static/js/ga.js"></script>
    
    <script type="text/javascript" src="_static/js/theme.js"></script>

    

  
  <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="_static/css/custom.css" type="text/css" />
    <link rel="index" title="Index" href="genindex.html" />
    <link rel="search" title="Search" href="search.html" />
    <link rel="next" title="Build 环境" href="build_env.html" />
    <link rel="prev" title="Build容器" href="build_a_container.html" /> 
</head>

<body class="wy-body-for-nav">

   
  <div class="wy-grid-for-nav">
    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >
          

          
            <a href="index.html" class="icon icon-home"> Singularity container
          

          
            
            <img src="_static/logo.png" class="logo" alt="Logo"/>
          
          </a>

          
            
            
              <div class="version">
                3.5
              </div>
            
          

          
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>

          
        </div>

        <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
          
            
            
              
            
            
              <ul>
<li class="toctree-l1"><a class="reference internal" href="introduction.html">介绍</a></li>
<li class="toctree-l1"><a class="reference internal" href="quick_start.html">快速入门</a></li>
<li class="toctree-l1"><a class="reference internal" href="security.html">Singularity安全</a></li>
</ul>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="build_a_container.html">Build容器</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Definition文件</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#id1">概述</a></li>
<li class="toctree-l2"><a class="reference internal" href="#header">Header</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#bootstrap-agents">常用的bootstrap agents</a></li>
<li class="toctree-l3"><a class="reference internal" href="#id4">其它bootstrap agents</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#sections">Sections</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#setup">%setup</a></li>
<li class="toctree-l3"><a class="reference internal" href="#files">%files</a></li>
<li class="toctree-l3"><a class="reference internal" href="#app">%app*</a></li>
<li class="toctree-l3"><a class="reference internal" href="#post">%post</a></li>
<li class="toctree-l3"><a class="reference internal" href="#test">%test</a></li>
<li class="toctree-l3"><a class="reference internal" href="#environment">%environment</a></li>
<li class="toctree-l3"><a class="reference internal" href="#startscript">%startscript</a></li>
<li class="toctree-l3"><a class="reference internal" href="#runscript">%runscript</a></li>
<li class="toctree-l3"><a class="reference internal" href="#labels">%labels</a></li>
<li class="toctree-l3"><a class="reference internal" href="#help">%help</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#build">多阶段Build</a></li>
<li class="toctree-l2"><a class="reference internal" href="#apps">Apps</a></li>
<li class="toctree-l2"><a class="reference internal" href="#id8">build容器的一些建议</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="build_env.html">Build环境</a></li>
<li class="toctree-l1"><a class="reference internal" href="singularity_and_docker.html">Singularity和Docker</a></li>
<li class="toctree-l1"><a class="reference internal" href="fakeroot.html">Fakeroot</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="signNverify.html">签名和认证</a></li>
<li class="toctree-l1"><a class="reference internal" href="key_commands.html">Key管理</a></li>
<li class="toctree-l1"><a class="reference internal" href="encryption.html">容器加密</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="endpoint.html">容器仓库</a></li>
<li class="toctree-l1"><a class="reference internal" href="cloud_library.html">Cloud Library</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="bind_paths_and_mounts.html">路径映射</a></li>
<li class="toctree-l1"><a class="reference internal" href="persistent_overlays.html">持久化Overlay</a></li>
<li class="toctree-l1"><a class="reference internal" href="running_services.html">运行服务</a></li>
<li class="toctree-l1"><a class="reference internal" href="environment_and_metadata.html">环境变量和元数据</a></li>
<li class="toctree-l1"><a class="reference internal" href="oci_runtime.html">OCI运行时</a></li>
<li class="toctree-l1"><a class="reference internal" href="plugins.html">插件</a></li>
<li class="toctree-l1"><a class="reference internal" href="security_options.html">安全选项</a></li>
<li class="toctree-l1"><a class="reference internal" href="networking.html">网络选项</a></li>
<li class="toctree-l1"><a class="reference internal" href="cgroups.html">Cgroups</a></li>
<li class="toctree-l1"><a class="reference internal" href="mpi.html">MPI应用</a></li>
<li class="toctree-l1"><a class="reference internal" href="gpu.html">GPU支持</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="contributing.html">Contributing</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="appendix.html">Appendix</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command Line Reference</a></li>
</ul>

            
          
        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" aria-label="top navigation">
        
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="index.html">Singularity container</a>
        
      </nav>


      <div class="wy-nav-content">
        
        <div class="rst-content style-external-links">
        
          















<div role="navigation" aria-label="breadcrumbs navigation">

  <ul class="wy-breadcrumbs">
    
      <li><a href="index.html">Docs</a> &raquo;</li>
        
      <li>Definition文件</li>
    
    
      <li class="wy-breadcrumbs-aside">
        
            
            
              <a href="https://github.com/sylabs/singularity-userdocs/blob/master/definition_files.rst" class="fa fa-github"> Edit on GitHub</a>
            
          
        
      </li>
    
  </ul>

  
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
            
  <div class="section" id="definition">
<span id="definitionfiles"></span><h1>Definition文件<a class="headerlink" href="#definition" title="Permalink to this headline">¶</a></h1>
<p id="sec-deffiles">一个singularity definition(def)文件是一个蓝本描述怎么build一个容器，和Dockerfile类似。
这个文件指定了基础容器，以及要在基础容器上安装的软件，要设置的环境变量，要从host上加到容器中的文件，和容器的metadata。</p>
<div class="section" id="id1">
<h2>概述<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h2>
<p>一个singlarity definition文件可以分为两部分:</p>
<ol class="arabic simple">
<li><p><strong>Header</strong>: Header部分描述了容器依赖的基础容器。</p></li>
<li><p><strong>Sections</strong>: 文件剩余部分包含多个sections(有时也叫做scriptlets或者blobs)。 每个section以%开始，后面跟上这个section的名字，section是可选的。
当build容器的时候， 使用 <code class="docutils literal notranslate"><span class="pre">/bin/sh</span></code> 执行每个section。当容器运行的时候，runscript默认的也是 <code class="docutils literal notranslate"><span class="pre">/bin/sh</span></code>，可以接受 <code class="docutils literal notranslate"><span class="pre">/bin/sh</span></code> 的参数。</p></li>
</ol>
<p>更过def文件的例子，<a class="reference external" href="https://github.com/sylabs/examples">请看这里</a>。
关于Dockerfile和Singularity definition文件的比较,  <a class="reference internal" href="singularity_and_docker.html#sec-deffile-vs-dockerfile"><span class="std std-ref">请参考这里</span></a>。</p>
</div>
<div class="section" id="header">
<h2>Header<a class="headerlink" href="#header" title="Permalink to this headline">¶</a></h2>
<p>header在def文件的顶部，header描述容器依赖的基础容器，它包含一些关键字。</p>
<p><code class="docutils literal notranslate"><span class="pre">Bootstrap</span></code> 关键字是必须的，它描述了你要使用哪种 <em>bootstrap agent</em> 获取基础容器。
比如如果Bootstrap是 <code class="docutils literal notranslate"><span class="pre">library</span></code>，那么将从 <a class="reference external" href="https://cloud.sylabs.io/library">Container Library</a> 获取基础容器。
同样的如果Bootstrap是 <code class="docutils literal notranslate"><span class="pre">docker</span></code>，那么将从 <a class="reference external" href="https://hub.docker.com/">Docker Hub</a> 获取基础容器。</p>
<p>从Singularity 3.2开始, <code class="docutils literal notranslate"><span class="pre">Bootstrap</span></code> 关键字必须出现在header的第一行，而以前的版本的则可以在header的任意位置。</p>
<p>根据 <code class="docutils literal notranslate"><span class="pre">Bootstrap</span></code> 的不同, header部分接下来的内容将不相同。
比如，当Bootstrap是 <code class="docutils literal notranslate"><span class="pre">library</span></code> 时,关键字 <code class="docutils literal notranslate"><span class="pre">From</span></code> 是有效的。</p>
<p>下面是从Container Library来获取debian基础容器:</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="k">Bootstrap</span>: library
<span class="k">From</span>: debian:<span class="m">7</span>
</pre></div>
</div>
<p>下面使用OS官方源安装CentOS-7:</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="k">Bootstrap</span>: yum
<span class="k">OSVersion</span>: <span class="m">7</span>
<span class="k">MirrorURL</span>: http://mirror.centos.org/centos-%{OSVERSION}/%{OSVERSION}/os/$basearch/
<span class="k">Include</span>: yum
</pre></div>
</div>
<p>每种不同的bootstrap agent都有自己的关键字和选项。你可以查看 <a class="reference internal" href="appendix.html#buildmodules"><span class="std std-ref">appendix section</span></a>:</p>
<div class="section" id="bootstrap-agents">
<h3>常用的bootstrap agents<a class="headerlink" href="#bootstrap-agents" title="Permalink to this headline">¶</a></h3>
<ul class="simple">
<li><p><a class="reference internal" href="appendix.html#build-library-module"><span class="std std-ref">library</span></a> (容器在 <a class="reference external" href="https://cloud.sylabs.io/library">Container Library</a>)</p></li>
<li><p><a class="reference internal" href="appendix.html#build-docker-module"><span class="std std-ref">docker</span></a> (容器在Docker Hub)</p></li>
<li><p><a class="reference internal" href="appendix.html#build-shub"><span class="std std-ref">shub</span></a> (容器在Singularity Hub)</p></li>
<li><p><a class="reference internal" href="appendix.html#build-oras"><span class="std std-ref">oras</span></a> (容器在支持的OCI的registries)</p></li>
<li><p><a class="reference internal" href="appendix.html#scratch-agent"><span class="std std-ref">scratch</span></a> (从0开始)</p></li>
</ul>
</div>
<div class="section" id="id4">
<h3>其它bootstrap agents<a class="headerlink" href="#id4" title="Permalink to this headline">¶</a></h3>
<ul class="simple">
<li><p><a class="reference internal" href="appendix.html#build-localimage"><span class="std std-ref">localimage</span></a> (容器在本机 saved on your machine)</p></li>
<li><p><a class="reference internal" href="appendix.html#build-yum"><span class="std std-ref">yum</span></a> (用于基于yum的CentOS和Scientific Linux)</p></li>
<li><p><a class="reference internal" href="appendix.html#build-debootstrap"><span class="std std-ref">debootstrap</span></a> (用于基于apt的Debian和Ubuntu)</p></li>
<li><p><a class="reference internal" href="singularity_and_docker.html#cli-oci-bootstrap-agent"><span class="std std-ref">oci</span></a> (OCI容器)</p></li>
<li><p><a class="reference internal" href="singularity_and_docker.html#cli-oci-archive-bootstrap-agent"><span class="std std-ref">oci-archive</span></a> (OCI容器打包文件)</p></li>
<li><p><a class="reference internal" href="appendix.html#docker-daemon-archive"><span class="std std-ref">docker-daemon</span></a> (容器在本机的docker daemon)</p></li>
<li><p><a class="reference internal" href="appendix.html#docker-daemon-archive"><span class="std std-ref">docker-archive</span></a> (容器是从docker导出的打包文件)</p></li>
<li><p><a class="reference internal" href="appendix.html#build-arch"><span class="std std-ref">arch</span></a> (Arch Linux)</p></li>
<li><p><a class="reference internal" href="appendix.html#build-busybox"><span class="std std-ref">busybox</span></a> (BusyBox)</p></li>
<li><p><a class="reference internal" href="appendix.html#build-zypper"><span class="std std-ref">zypper</span></a> (用于基于zypper的Suse和OpenSuse)</p></li>
</ul>
</div>
</div>
<div class="section" id="sections">
<h2>Sections<a class="headerlink" href="#sections" title="Permalink to this headline">¶</a></h2>
<p>definition文件包含多个sections，不同的section添加不同的内容到容器或者在build容器的时候执行命令。
在build容器过程中，任何一条命令执行失败，build过程将停止。</p>
<p>下面是一个例子，其用到了所有的section类型，后面我们将一个个讨论这些不同的section。
当然一个def文件并不需要每种类型的section都包括。
另外，如果def文件中有多个同名的section，在build过程中后面section的内容会追加到前面的section中。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="k">Bootstrap</span>: library
<span class="k">From</span>: ubuntu:<span class="m">18.04</span>
Stage: build

<span class="gh">%setup</span>
    touch /file1
    touch <span class="si">${</span><span class="nv">SINGULARITY_ROOTFS</span><span class="si">}</span>/file2

<span class="gh">%files</span>
    /file1
    /file1 /opt

<span class="gh">%environment</span>
    <span class="nb">export</span> <span class="nv">LISTEN_PORT</span><span class="o">=</span><span class="m">12345</span>
    <span class="nb">export</span> <span class="nv">LC_ALL</span><span class="o">=</span>C

<span class="gh">%post</span>
    apt-get update <span class="o">&amp;&amp;</span> apt-get install -y netcat
    <span class="nv">NOW</span><span class="o">=</span><span class="sb">`</span>date<span class="sb">`</span>
    <span class="nb">echo</span> <span class="s2">&quot;export NOW=\&quot;</span><span class="si">${</span><span class="nv">NOW</span><span class="si">}</span><span class="s2">\&quot;&quot;</span> &gt;&gt; <span class="nv">$SINGULARITY_ENVIRONMENT</span>

<span class="gh">%runscript</span>
    <span class="nb">echo</span> <span class="s2">&quot;Container was created </span><span class="nv">$NOW</span><span class="s2">&quot;</span>
    <span class="nb">echo</span> <span class="s2">&quot;Arguments received: </span><span class="nv">$*</span><span class="s2">&quot;</span>
    <span class="nb">exec</span> <span class="nb">echo</span> <span class="s2">&quot;</span><span class="nv">$@</span><span class="s2">&quot;</span>

<span class="gh">%startscript</span>
    nc -lp <span class="nv">$LISTEN_PORT</span>

<span class="gh">%test</span>
    grep -q <span class="nv">NAME</span><span class="o">=</span><span class="se">\&quot;</span>Ubuntu<span class="se">\&quot;</span> /etc/os-release
    <span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> -eq <span class="m">0</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
        <span class="nb">echo</span> <span class="s2">&quot;Container base is Ubuntu as expected.&quot;</span>
    <span class="k">else</span>
        <span class="nb">echo</span> <span class="s2">&quot;Container base is not Ubuntu.&quot;</span>
    <span class="k">fi</span>

<span class="gh">%labels</span>
    Author d@sylabs.io
    Version v0.0.1

<span class="gh">%help</span>
    This is a demo container used to illustrate a def file that uses all
    supported sections.
</pre></div>
</div>
<p>Section在def文件中的位置不重要。</p>
<div class="section" id="setup">
<h3>%setup<a class="headerlink" href="#setup" title="Permalink to this headline">¶</a></h3>
<p>build容器过程中，在 <code class="docutils literal notranslate"><span class="pre">%setup</span></code> section的命令会首先执行，并且这些命令是在host上执行，而不是容器内部执行。
你可以通过环境变量``$SINGULARITY_ROOTFS``获取容器的文件系统。</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>在build容器的时候，由于 <code class="docutils literal notranslate"><span class="pre">%setup</span></code> section下的命令是在容器外执行，因此要小心使用，不要对host造成破坏。</p>
</div>
<p>上面的例子中:</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%setup</span>
    touch /file1
    touch <span class="si">${</span><span class="nv">SINGULARITY_ROOTFS</span><span class="si">}</span>/file2
</pre></div>
</div>
<p>在 <strong>host</strong> 根目录下创建 <code class="docutils literal notranslate"><span class="pre">file1</span></code>，这个文件我们在 <code class="docutils literal notranslate"><span class="pre">%files</span></code> section会用到。在 <strong>container</strong> 内的根目录下创建 <code class="docutils literal notranslate"><span class="pre">file2</span></code>。</p>
<p>后面的 <code class="docutils literal notranslate"><span class="pre">%files</span></code> section提供了安全的方法拷贝host上的文件到container中，
由于使用 <code class="docutils literal notranslate"><span class="pre">%setup</span></code> 有可能会对host造成破坏，因此 <code class="docutils literal notranslate"><span class="pre">%setup</span></code> 不建议使用。</p>
</div>
<div class="section" id="files">
<h3>%files<a class="headerlink" href="#files" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">%files</span></code> section 允许你拷贝host上的文件到容器中:</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%files</span> <span class="o">[</span>from &lt;stage&gt;<span class="o">]</span>
    &lt;source&gt; <span class="o">[</span>&lt;destination&gt;<span class="o">]</span>
    ...
</pre></div>
</div>
<p>每行是一个 <code class="docutils literal notranslate"><span class="pre">&lt;source&gt;</span></code> 和 <code class="docutils literal notranslate"><span class="pre">&lt;destination&gt;</span></code> 对。  <code class="docutils literal notranslate"><span class="pre">&lt;source&gt;</span></code> 可以是:</p>
<blockquote>
<div><ol class="arabic simple">
<li><p>host上的一个路径</p></li>
<li><p>前面阶段已经build出的文件的路径</p></li>
</ol>
</div></blockquote>
<p><code class="docutils literal notranslate"><span class="pre">&lt;destination&gt;</span></code> 是container内的路径。如果没有提供 <code class="docutils literal notranslate"><span class="pre">&lt;destination&gt;</span></code>，那么 <code class="docutils literal notranslate"><span class="pre">&lt;destination&gt;</span></code>
和 <code class="docutils literal notranslate"><span class="pre">&lt;source&gt;</span></code> 内容一样。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%files</span>
    /file1
    /file1 /opt
</pre></div>
</div>
<p>第一行将拷贝host的根目录下的 <code class="docutils literal notranslate"><span class="pre">file1</span></code> 到container中的根目录下。
第一行将拷贝host的根目录下的 <code class="docutils literal notranslate"><span class="pre">file1</span></code> 到container中的/opt目录下。</p>
<p>definition文件中其它阶段生成的文件也可以拷贝到当前阶段中使用。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%files</span> from stage_name
  /root/hello /bin/hello
</pre></div>
</div>
<p>不同的时，host文件拷贝到container中，没有生成软链接，而其它阶段的文件拷贝到当前阶段，实际上是生成一个软链接。</p>
<p><code class="docutils literal notranslate"><span class="pre">%files</span></code> 会在 <code class="docutils literal notranslate"><span class="pre">%post</span></code> 之前执行。</p>
</div>
<div class="section" id="app">
<h3>%app*<a class="headerlink" href="#app" title="Permalink to this headline">¶</a></h3>
<p>某些情况下，如果对每个app都build一个容器，由于这些app的依赖基本都相同，因此这些容器之间是冗余的。
因此基于 <a class="reference external" href="https://sci-f.github.io/">Standard Container Integration Format (SCI-F)</a>，
singularity支持在一个容器中安装多个apps，更多关于app的信息，请查看 <a class="reference internal" href="#apps"><span class="std std-ref">这里</span></a>。</p>
</div>
<div class="section" id="post">
<h3>%post<a class="headerlink" href="#post" title="Permalink to this headline">¶</a></h3>
<p>在这一section，你可以从网络下载一些工具，像 <code class="docutils literal notranslate"><span class="pre">git</span></code> 和 <code class="docutils literal notranslate"><span class="pre">wget</span></code>, 你可以使用这些工具下载软件并安装这些软件，当然你也可以创建和修改文件等。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%post</span>
    apt-get update <span class="o">&amp;&amp;</span> apt-get install -y netcat
    <span class="nv">NOW</span><span class="o">=</span><span class="sb">`</span>date<span class="sb">`</span>
    <span class="nb">echo</span> <span class="s2">&quot;export NOW=\&quot;</span><span class="si">${</span><span class="nv">NOW</span><span class="si">}</span><span class="s2">\&quot;&quot;</span> &gt;&gt; <span class="nv">$SINGULARITY_ENVIRONMENT</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">%post</span></code> 使用Ubuntu包管理器 <code class="docutils literal notranslate"><span class="pre">apt</span></code> 更新系统和安装软件 <code class="docutils literal notranslate"><span class="pre">netcat</span></code> ( <code class="docutils literal notranslate"><span class="pre">%startscript</span></code> 将会用到这个软件)。</p>
<p>你不能在 <code class="docutils literal notranslate"><span class="pre">%environment</span></code> 中设置$SINGULARITY_ENVIRONMENT的值，将文本写入$SINGULARITY_ENVIRONMENT，
最终实际上会写入容器中的文件 <code class="docutils literal notranslate"><span class="pre">/.singularity.d/env/91-environment.sh</span></code>，然后在运行的时候自动source这个文件。</p>
</div>
<div class="section" id="test">
<h3>%test<a class="headerlink" href="#test" title="Permalink to this headline">¶</a></h3>
<p>在build容器时候，最后会运行 <code class="docutils literal notranslate"><span class="pre">%test</span></code> 下面的脚本来测试进行容器，容器build好以后，你可以使用 <code class="docutils literal notranslate"><span class="pre">test</span></code> 命令运行 <code class="docutils literal notranslate"><span class="pre">%test</span></code> 下面的脚本。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%test</span>
    grep -q <span class="nv">NAME</span><span class="o">=</span><span class="se">\&quot;</span>Ubuntu<span class="se">\&quot;</span> /etc/os-release
    <span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> -eq <span class="m">0</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
        <span class="nb">echo</span> <span class="s2">&quot;Container base is Ubuntu as expected.&quot;</span>
    <span class="k">else</span>
        <span class="nb">echo</span> <span class="s2">&quot;Container base is not Ubuntu.&quot;</span>
    <span class="k">fi</span>
</pre></div>
</div>
<p>这段%test用来check基础OS是否为Ubuntu。
如果在build的时候不希望运行%test，可以使用 <code class="docutils literal notranslate"><span class="pre">--notest</span></code> 的选项。
容器build好以后，可以使用test命令运行%test下的脚本。</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>$ sudo singularity build --notest my_container.sif my_container.def

$ singularity test my_container.sif
Container base is Ubuntu as expected.
</pre></div>
</div>
</div>
<div class="section" id="environment">
<h3>%environment<a class="headerlink" href="#environment" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">%environment</span></code> 可以设置容器运行时的环境变量。
需要注意的是，这里定义的环境变量在build阶段不能使用。
在build阶段如果要使用环境变量，需要在 <code class="docutils literal notranslate"><span class="pre">%post</span></code> 里面定义和使用:</p>
<ul class="simple">
<li><p><strong>build阶段</strong>: <code class="docutils literal notranslate"><span class="pre">%environment</span></code> 下面的环境变量会被写到容器的metadata文件夹下的一个文件中，build的时候这个文件不会被source使用。</p></li>
<li><p><strong>运行阶段</strong>: metadata文件夹下的文件被source，可以使用定义的环境变量。</p></li>
</ul>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%environment</span>
    <span class="nb">export</span> <span class="nv">LISTEN_PORT</span><span class="o">=</span><span class="m">12345</span>
    <span class="nb">export</span> <span class="nv">LC_ALL</span><span class="o">=</span>C
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">%startscript</span></code> 将会用到 <code class="docutils literal notranslate"><span class="pre">$LISTEN_PORT</span></code> 环境变量,
<code class="docutils literal notranslate"><span class="pre">$LC_ALL</span></code> 会被很多程序（通常是perl程序）用到。容器build好以后，你可以验证环境变量是否生效。</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>$ singularity exec my_container.sif env | grep -E &#39;LISTEN_PORT|LC_ALL&#39;
LISTEN_PORT=12345
LC_ALL=C
</pre></div>
</div>
<p>你也可以在 <code class="docutils literal notranslate"><span class="pre">%post</span></code> 里面设置环境变量。</p>
<p>build容器的时候,  <code class="docutils literal notranslate"><span class="pre">%environment</span></code> 下的内容写到容器中的文件 <code class="docutils literal notranslate"><span class="pre">/.singularity.d/env/90-environment.sh</span></code> 中。
<code class="docutils literal notranslate"><span class="pre">%post</span></code> 中如果通过命令将内容写入 <code class="docutils literal notranslate"><span class="pre">$SINGULARITY_ENVIRONMENT</span></code>，
那么这些内容实际上是写入了文件 <code class="docutils literal notranslate"><span class="pre">/.singularity.d/env/91-environment.sh</span></code> 中。</p>
<p>运行容器的时候, 在 <code class="docutils literal notranslate"><span class="pre">/.singularity.d/env</span></code> 下面的文件会按照顺序被source。
91-environment.sh会在90-environment.sh后被source，
因此这个例子中 <code class="docutils literal notranslate"><span class="pre">%post</span></code> 中写入的变量会优先于 <code class="docutils literal notranslate"><span class="pre">%environment</span></code> 中设置的变量。</p>
<p>关于singularity环境变量和metadata，请参考 <a class="reference internal" href="environment_and_metadata.html#environment-and-metadata"><span class="std std-ref">Environment and Metadata</span></a>。</p>
</div>
<div class="section" id="startscript">
<span id="id5"></span><h3>%startscript<a class="headerlink" href="#startscript" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">%startscript</span></code> 下的内容在build的时候会写入容器中的一个文件，在运行 <code class="docutils literal notranslate"><span class="pre">instance</span> <span class="pre">start</span></code> 命令的时候会执行这个文件。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%startscript</span>
    nc -lp <span class="nv">$LISTEN_PORT</span>
</pre></div>
</div>
<p>这里netcat程序侦听TCP端口，这个端口是在 <code class="docutils literal notranslate"><span class="pre">%environment</span></code> 中设置的。</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>$ singularity instance start my_container.sif instance1
INFO:    instance started successfully

$ lsof | grep LISTEN
nc        19061               vagrant    3u     IPv4             107409      0t0        TCP *:12345 (LISTEN)

$ singularity instance stop instance1
Stopping instance1 instance of /home/vagrant/my_container.sif (PID=19035)
</pre></div>
</div>
</div>
<div class="section" id="runscript">
<span id="id6"></span><h3>%runscript<a class="headerlink" href="#runscript" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">%runscript</span></code> 下的内容在build的时候会写入容器中的一个文件，
在运行 <code class="docutils literal notranslate"><span class="pre">singularity</span> <span class="pre">run</span></code> 命令或者直接运行容器的时候会执行这个文件。
当容器运行的时候，容器后面跟的参数会传给这个文件，这意味着在这个文件中你可以处理传递过来的参数。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%runscript</span>
    <span class="nb">echo</span> <span class="s2">&quot;Container was created </span><span class="nv">$NOW</span><span class="s2">&quot;</span>
    <span class="nb">echo</span> <span class="s2">&quot;Arguments received: </span><span class="nv">$*</span><span class="s2">&quot;</span>
    <span class="nb">exec</span> <span class="nb">echo</span> <span class="s2">&quot;</span><span class="nv">$@</span><span class="s2">&quot;</span>
</pre></div>
</div>
<p>上述运行脚本中，首先会打出容器创建的时间 <code class="docutils literal notranslate"><span class="pre">$NOW</span></code> (这个变量是在 <code class="docutils literal notranslate"><span class="pre">%post</span></code> 中设置的)。
接着将传递给这个容器的所有参数作为一个字符串打印出来，然后讲所有参数以字符串数组方式传递给echo。
<code class="docutils literal notranslate"><span class="pre">exec</span></code> 用来生成一个新的echo进程来代替进入容器时的进程（shell进程），shell进程会结束，echo进程在容器中运行。</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>$ ./my_container.sif
Container was created Thu Dec  6 20:01:56 UTC 2018
Arguments received:

$ ./my_container.sif this that and the other
Container was created Thu Dec  6 20:01:56 UTC 2018
Arguments received: this that and the other
this that and the other
</pre></div>
</div>
</div>
<div class="section" id="labels">
<h3>%labels<a class="headerlink" href="#labels" title="Permalink to this headline">¶</a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">%labels</span></code> 用来添加metadata到容器文件 <code class="docutils literal notranslate"><span class="pre">/.singularity.d/labels.json</span></code> 中。
其格式是”名字 值”。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%labels</span>
    Author d@sylabs.io
    Version v0.0.1
    MyLabel Hello World
</pre></div>
</div>
<p>添加label，只需要在lables下面每行的第一个空格后面加上”名字 值”就可以。</p>
<p>上面例子中, 第一个label是 <code class="docutils literal notranslate"><span class="pre">Author</span></code>，其值为 <code class="docutils literal notranslate"><span class="pre">d&#64;sylabs.io</span></code>。
第二个label是 <code class="docutils literal notranslate"><span class="pre">Version</span></code>，其值为 <code class="docutils literal notranslate"><span class="pre">v0.0.1</span></code>。
最后一个label是 <code class="docutils literal notranslate"><span class="pre">MyLabel</span></code>，其值为 <code class="docutils literal notranslate"><span class="pre">Hello</span> <span class="pre">World</span></code>。</p>
<p>你可以用inspect命令来查看容器的所有label。</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>$ singularity inspect my_container.sif

{
  &quot;Author&quot;: &quot;d@sylabs.io&quot;,
  &quot;Version&quot;: &quot;v0.0.1&quot;,
  &quot;MyLabel&quot;: &quot;Hello World&quot;,
  &quot;org.label-schema.build-date&quot;: &quot;Thursday_6_December_2018_20:1:56_UTC&quot;,
  &quot;org.label-schema.schema-version&quot;: &quot;1.0&quot;,
  &quot;org.label-schema.usage&quot;: &quot;/.singularity.d/runscript.help&quot;,
  &quot;org.label-schema.usage.singularity.deffile.bootstrap&quot;: &quot;library&quot;,
  &quot;org.label-schema.usage.singularity.deffile.from&quot;: &quot;ubuntu:18.04&quot;,
  &quot;org.label-schema.usage.singularity.runscript.help&quot;: &quot;/.singularity.d/runscript.help&quot;,
  &quot;org.label-schema.usage.singularity.version&quot;: &quot;3.0.1&quot;
}
</pre></div>
</div>
<p>上面有些label是build的过程中自动生成的。关于label和metadata的更多信息，请参考 <a class="reference internal" href="environment_and_metadata.html#environment-and-metadata"><span class="std std-ref">这里</span></a>。</p>
</div>
<div class="section" id="help">
<h3>%help<a class="headerlink" href="#help" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">%help</span></code> 下的内容在build的时候会写入容器中的一个metadata文件。
<code class="docutils literal notranslate"><span class="pre">run-help</span></code> 命令能查看 <code class="docutils literal notranslate"><span class="pre">%help</span></code> 的内容。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="gh">%help</span>
    This is a demo container used to illustrate a def file that uses all
    supported sections.
</pre></div>
</div>
<p>容器build好以后，使用下面命令查看%help的内容:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>$ singularity run-help my_container.sif
    This is a demo container used to illustrate a def file that uses all
    supported sections.
</pre></div>
</div>
</div>
</div>
<div class="section" id="build">
<h2>多阶段Build<a class="headerlink" href="#build" title="Permalink to this headline">¶</a></h2>
<p>Singularity从3.2开始支持多阶段build，
比如一个阶段先在一个环境中编译出一个二进制文件，在最终阶段中可以拷贝这个二进制文件到最终容器，这样就减小了容器的大小。</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="k">Bootstrap</span>: docker
<span class="k">From</span>: golang:<span class="m">1.12.3</span>-alpine3<span class="m">.9</span>
Stage: devel

<span class="gh">%post</span>
  <span class="c1"># prep environment</span>
  <span class="nb">export</span> <span class="nv">PATH</span><span class="o">=</span><span class="s2">&quot;/go/bin:/usr/local/go/bin:</span><span class="nv">$PATH</span><span class="s2">&quot;</span>
  <span class="nb">export</span> <span class="nv">HOME</span><span class="o">=</span><span class="s2">&quot;/root&quot;</span>
  <span class="nb">cd</span> /root

  <span class="c1"># insert source code, could also be copied from host with %files</span>
  cat <span class="s">&lt;&lt; EOF &gt; hello.go</span>
<span class="s">  package main</span>
<span class="s">  import &quot;fmt&quot;</span>

<span class="s">  func main() {</span>
<span class="s">    fmt.Printf(&quot;Hello World!\n&quot;)</span>
<span class="s">  }</span>
<span class="s">EOF</span>

  go build -o hello hello.go


<span class="c1"># Install binary into final image</span>
Bootstrap: library
From: alpine:3.9
Stage: final

<span class="c1"># install binary from stage one</span>
<span class="gh">%files</span> from devel
  /root/hello /bin/hello
</pre></div>
</div>
<p>每个阶段的名字可以随意命名。每个阶段内的执行和单阶段执行相同。声明靠后的阶段可以拷贝前面的阶段的文件到当前阶段，
但是声明靠前的阶段不能拷贝声明靠后文件。因此 <code class="docutils literal notranslate"><span class="pre">final</span></code> 阶段能拷贝 <code class="docutils literal notranslate"><span class="pre">devel</span></code> 阶段的文件，而 <code class="docutils literal notranslate"><span class="pre">devel</span></code> 阶段不能拷贝 <code class="docutils literal notranslate"><span class="pre">final</span></code> 阶段的文件。</p>
</div>
<div class="section" id="apps">
<span id="id7"></span><h2>Apps<a class="headerlink" href="#apps" title="Permalink to this headline">¶</a></h2>
<p><code class="docutils literal notranslate"><span class="pre">%app*</span></code> 是相对独立的section。一个def文件可以有多个app，app之间没有顺序的关系。</p>
<p>The following runscript demonstrates how to build 2 different apps into the
same container using SCI-F modules:</p>
<div class="highlight-singularity notranslate"><div class="highlight"><pre><span></span><span class="k">Bootstrap</span>: docker
<span class="k">From</span>: ubuntu

<span class="gh">%environment</span>
    <span class="nv">GLOBAL</span><span class="o">=</span>variables
    <span class="nv">AVAILABLE</span><span class="o">=</span><span class="s2">&quot;to all apps&quot;</span>

<span class="c1">##############################</span>
<span class="c1"># foo</span>
<span class="c1">##############################</span>

<span class="gh">%apprun</span> foo
    <span class="nb">exec</span> <span class="nb">echo</span> <span class="s2">&quot;RUNNING FOO&quot;</span>

<span class="gh">%applabels</span> foo
   BESTAPP FOO

<span class="gh">%appinstall</span> foo
   touch foo.exec

<span class="gh">%appenv</span> foo
    <span class="nv">SOFTWARE</span><span class="o">=</span>foo
    <span class="nb">export</span> SOFTWARE

<span class="gh">%apphelp</span> foo
    This is the <span class="nb">help</span> <span class="k">for</span> foo.

<span class="gh">%appfiles</span> foo
   foo.txt

<span class="c1">##############################</span>
<span class="c1"># bar</span>
<span class="c1">##############################</span>

<span class="gh">%apphelp</span> bar
    This is the <span class="nb">help</span> <span class="k">for</span> bar.

<span class="gh">%applabels</span> bar
   BESTAPP BAR

<span class="gh">%appinstall</span> bar
    touch bar.exec

<span class="gh">%appenv</span> bar
    <span class="nv">SOFTWARE</span><span class="o">=</span>bar
    <span class="nb">export</span> SOFTWARE
</pre></div>
</div>
<p>对一个app来说，<code class="docutils literal notranslate"><span class="pre">%appinstall</span></code> 和 <code class="docutils literal notranslate"><span class="pre">%post</span></code> 等价， <code class="docutils literal notranslate"><span class="pre">%appenv</span></code> 和 <code class="docutils literal notranslate"><span class="pre">%environment</span></code> 等价。</p>
<p>使用app:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>% singularity run --app foo my_container.sif
RUNNING FOO
</pre></div>
</div>
<p>两个app中都定义了 <code class="docutils literal notranslate"><span class="pre">$SOFTWARE</span></code>。你可以执行下面的命令查看当前app能用的环境变量。</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>$ singularity exec --app foo my_container.sif env | grep SOFTWARE
SOFTWARE=foo

$ singularity exec --app bar my_container.sif env | grep SOFTWARE
SOFTWARE=bar
</pre></div>
</div>
</div>
<div class="section" id="id8">
<h2>build容器的一些建议<a class="headerlink" href="#id8" title="Permalink to this headline">¶</a></h2>
<ol class="arabic simple">
<li><p>在容器中安装程序和创建文件的时候，这些程序和文件放在系统目录下，不要放在 <code class="docutils literal notranslate"><span class="pre">/home</span></code>, <code class="docutils literal notranslate"><span class="pre">/tmp</span></code> 等有可能被mount覆盖的目录。</p></li>
<li><p>添加容器的描述和说明，如果你的runscript不能提供帮助说明，在
<code class="docutils literal notranslate"><span class="pre">%help</span></code> 或者 <code class="docutils literal notranslate"><span class="pre">%apphelp</span></code> 写上帮助说明， 一个好的容器应该告诉用户怎么使用它。</p></li>
<li><p>如果你需要添加环境变量，添加到 <code class="docutils literal notranslate"><span class="pre">%environment</span></code> 和 <code class="docutils literal notranslate"><span class="pre">%appenv</span></code> 中。</p></li>
<li><p>在容器中创建的文件，其所有者应该是系统中用户id小于500的用户。</p></li>
<li><p>确保一些敏感文件像 <code class="docutils literal notranslate"><span class="pre">/etc/passwd</span></code>, <code class="docutils literal notranslate"><span class="pre">/etc/group</span></code> 和 <code class="docutils literal notranslate"><span class="pre">/etc/shadow</span></code> 不包含密码。</p></li>
<li><p>用def文件Build容器，不要使用sandbox这种黑盒子的方式。</p></li>
</ol>
</div>
</div>


           </div>
           
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="build_env.html" class="btn btn-neutral float-right" title="Build 环境" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right"></span></a>
      
      
        <a href="build_a_container.html" class="btn btn-neutral float-left" title="Build容器" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div role="contentinfo">
    <p>
        &copy; Copyright 2017-2019, Sylabs Inc

    </p>
  </div>
  Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 

</footer>

        </div>
      </div>

    </section>

  </div>
  


  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script>

  
  
    
   

</body>
</html>